package com.yjk.dzpoke.websocket.bean;

import cn.hutool.json.JSONUtil;
import com.yjk.dzpoke.websocket.PlayServer;
import lombok.Data;

import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

@Data
public class Game {

    private String id;

    /**
     * 本局游戏的玩家
     */
    private List<String> players = new ArrayList<>();

    private Map<String, String> playerName = new HashMap<>();

    /**
     * 玩家筹码值
     */
    private Map<String, Integer> pointMap = new HashMap<>();

    /**
     * 本轮庄家
     */
    private String mainPlayer;

    /**
     * 当前轮次
     */
    private GameTurn gameTurn;

    private String player(String playerId) {
        String name = playerName.get(playerId);
        if (name == null) return "未知玩家";
        else return name;
    }

    public void init(String gameId, List<PlayServer> playersIn, Integer startPoint) {
        id = gameId;
        for (PlayServer playServer : playersIn) {
            playerName.put(playServer.getSessionId(), playServer.getPlayerName());
        }
        players.addAll(playersIn.stream().map(PlayServer::getSessionId).collect(Collectors.toList()));
        Collections.shuffle(players);
        for (String player : players) {
            pointMap.put(player, startPoint);
        }
        mainPlayer = players.get(0);
    }

    /**
     * 开始一轮游戏
     *
     * @return
     */
    public GameTurn startTurn(List<Poke> pokes) {
        GameTurn gt;
        int i = players.indexOf(mainPlayer);
        if (i != 0) {
            List<String> playerSequence = new ArrayList<>();
            playerSequence.addAll(players.subList(i, players.size()));
            playerSequence.addAll(players.subList(0, i));
            gt = new GameTurn(playerSequence, pointMap);
        } else {
            gt = new GameTurn(players, pointMap);
        }
        if (i == players.size() - 1) {
            mainPlayer = players.get(0);
        } else
            mainPlayer = players.get(i + 1);
        gt.setPokes(pokes);
        return gt;
    }

    public void start() throws InterruptedException {
        PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                WsMsg.chatMsg("游戏", "洗一副新牌。")
        )).toString());
        List<Poke> pokes = Poke.NewPokes();
        for (int i = 1; i <= 10; i++) {
            PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                    WsMsg.chatMsg("游戏", String.format("第%d轮游戏开始。", i))
            )).toString());

            if (pokes.size() < players.size() * 2 + 5) {
                pokes = Poke.NewPokes();
                PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                        WsMsg.chatMsg("游戏", "重新洗牌。")
                )).toString());
            }
            GameTurn gameTurn = startTurn(pokes);
            this.gameTurn = gameTurn;
            //盲注
            gameTurn.mz();
            PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                    WsMsg.chatMsg("游戏", String.format("盲注阶段。小盲%s下注%d，大盲%s下注%d", player(gameTurn.getSmallBet()), gameTurn.getBase() / 2, player(gameTurn.getBigBet()), gameTurn.getBase()))
            )).toString());
            //发送底牌
            for (Map.Entry<String, List<Poke>> entry : gameTurn.getPokeMap().entrySet()) {
                String player = entry.getKey();
                List<Poke> privatePoke = entry.getValue();
                PlayServer.sendMessage(player, JSONUtil.parse(Arrays.asList(
                        WsMsg.privatePoke(privatePoke),
                        WsMsg.chatMsg("游戏", "你的底牌是" + privatePoke)
                )).toString());
            }

            while (gameTurn.nextStatus()) {
                if (gameTurn.getStatus() > 1) {
                    PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                            WsMsg.publicPoke(gameTurn.getPublicPoke()),
                            WsMsg.chatMsg("游戏", "公共牌是" + gameTurn.getPublicPoke())
                    )).toString());
                }
                Choice choice = gameTurn.getPlayerChoice();
                while (!choice.getEnd()) {
                    System.out.println("玩家选择");
                    String player = player(gameTurn.getCurrentPlayer());
                    PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                            WsMsg.chatMsg("游戏", "等待" + player + "做选择。")
                    )).toString());

                    PlayServer.sendMessage(gameTurn.getCurrentPlayer(), JSONUtil.parse(Arrays.asList(
                            WsMsg.choice(choice)
                    )).toString());

                    String msg = gameTurn.deal();
                    PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                            WsMsg.chatMsg("游戏", player + msg)
                    )).toString());
                    choice = gameTurn.getPlayerChoice();
                }
            }

            List<String> winners = new ArrayList<>();
            PokeType pokeType = null;
            for (String player : players) {
                List<Poke> hand = gameTurn.getPokeMap().get(player);
                PokeType type = PokeType.getType(hand, gameTurn.getPublicPoke());
                if (winners.isEmpty()) {
                    winners.add(player);
                    pokeType = type;
                } else {
                    if (pokeType.compareTo(type) < 0) {
                        winners.clear();
                        winners.add(player);
                        pokeType = type;
                    } else if (pokeType.compareTo(type) == 0) {
                        winners.add(player);
                    }
                }
            }

            if (winners.size() == 1) {
                String winner = winners.get(0);
                pointMap.put(winner, pointMap.get(winner) + gameTurn.getPool());
                PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                        WsMsg.chatMsg("游戏", player(winner) + "获胜，牌型是" + pokeType + " 获得奖池" + gameTurn.getPool()),
                        WsMsg.chatMsg("游戏", "即将开始下一轮游戏")
                )).toString());
                Thread.sleep(5000);
            } else {
                String winner = "";
                int avg = gameTurn.getPool() / winners.size();
                int other = gameTurn.getPool() % winners.size();

                for (String playerId : winners) {
                    winner += (player(playerId) + " ");
                    pointMap.put(playerId, pointMap.get(playerId) + avg);
                }

                if (other != 0) {

                }

                PlayServer.sendMessageByIds(players, JSONUtil.parse(Arrays.asList(
                        WsMsg.chatMsg("游戏", winner + "获胜，牌型是" + pokeType + " 平分奖池"),
                        WsMsg.chatMsg("游戏", "即将开始下一轮游戏")
                )).toString());
                Thread.sleep(5000);
            }
        }
    }
}
